import { AxiosProgressEvent } from 'axios';
import { ElMessage, UploadFiles } from 'element-plus';
import { UploadUserFile } from 'element-plus/es/components/upload/src/upload';
import { defineStore } from 'pinia';
import {
  CreateActionSuccessfully,
  createdSuccessfully,
  getDatasetReq,
  getFileId,
  getImportReq,
  getPresignedUrls,
  getPresignedUrlsReq,
  getSuccessReq,
  getUploadId,
  getUploadList,
  getUploadReq,
  importFile,
  mergeChunks,
  updateErrorStatus,
  updateImporting,
  updateItemStatus,
  updateStatus,
} from 'src/api/dataCenter';
import { authedApi } from 'src/utils/axios';

/* 创建切片进度条 */
export const OnFileProgress = (item: FileChunk | FileNoChunk) => {
  return (e: AxiosProgressEvent) => {
    item.percentage = parseInt(String((e.loaded / (e.total || 0)) * 100));
  };
};

/* 创建文件切片 */
export const createFileChunk = (file: File, size: number): FileRowChuck => {
  const fileChunkList: FileRowChuck = [];
  let cur = 0;
  while (cur < file.size) {
    fileChunkList.push({ file: file.slice(cur, cur + size) });
    cur += size;
  }
  return fileChunkList;
};

export const uploadErrorQueueItem = (req: CreateActionSuccessfully) => {
  return updateErrorStatus(req);
};
export interface PlatformUploadLoading {
  beforeStartUploading: boolean;
}
// const platformReUploadStore = usePlatformReUploadStore()
/*
 * 请求优先级：
 * upload: 0 最高
 * success_upload: 1
 * merge: 2
 * import: 3
 * success: 4
 * fetch_dataset: 5
 * clean: 999
 *
 * */

export const usePlatformUploadStore = defineStore('platformUploadStore', {
  state: () => ({
    platformMaxFileSize: 2 * 1024 * 1024 * 1024,
    platformChunkSize: 10 * 1024 * 1024,
    platformUploadCount: 0,
    platformCurType: 'dataset' as 'featureSet' | 'dataset',
    platformCurrentProcessId: [] as number[],
    platformCurrentUploadId: 0 as number,
    platformPermitScheduler: false,
    platformUploadModalShow: false,
    platformDatasetStatusChange: false,
    platformCurrentUploadDataset: {} as {
      dataset_id: number;
      version_id: number;
      project_id: string;
    },
    platformUploadLoading: {
      beforeStartUploading: false,
    } as PlatformUploadLoading,
    platformJumpRequestId: [] as number[],
    platformFailureDatasetId: [] as number[],
    platformDeleteDatasetId: [] as number[],
    platformMaxUploadRequestNum: 1,
    platformRequestChunkSignal: false,
    platformRequestSignal: false,
    platformUploadIdMapper: {} as Record<string, Record<string, string>>,
    platformUploadUrlsMapper: {} as Record<string, Record<string, string[]>>,
    platformFileIdMapper: {} as Record<string, Record<string, string>>,
    platformUploadQueue: [] as platformUploadQueue[],
    platformUploadFileList: {} as Record<string, PlatformUploadUserFile[]>,
    platformUploadList: [] as UploadList[],
    platformDataSetFileContainer: {} as Record<string, FileContainer>,
    vueUploadComponentFileList: [] as UploadUserFile[],
    reUploadList: [] as UploadList[],
  }),
  actions: {
    setReUploadList(lists: UploadList[]) {
      this.reUploadList = lists;
    },
    setCurUploadDataset(dataset: CurrentDataset) {
      this.platformCurrentUploadDataset = {
        dataset_id: Number(dataset.id),
        version_id: dataset.version_id,
        project_id: dataset.project_id,
      };
    },
    excludeErrorId(id: number) {
      this.platformFailureDatasetId = this.platformFailureDatasetId.filter(
        (id_) => id_ != id
      );
      this.platformCurrentProcessId = this.platformCurrentProcessId.filter(
        (id_) => id_ != id
      );
    },
    excludeDelId(id: number) {
      this.platformDeleteDatasetId = this.platformDeleteDatasetId.filter(
        (_id) => _id != id
      );
    },
    setCurProcessDatasetIds(id: number[]) {
      this.platformCurrentProcessId = id;
    },
    setCurProcessDatasetId(id: number) {
      this.platformCurrentProcessId.push(id);
      this.platformCurrentUploadId = id;
    },
    pushFileList(uploadFile: UploadUserFile) {
      this.vueUploadComponentFileList.push(uploadFile);
    },
    setFileList(uploadFiles: UploadFiles) {
      this.vueUploadComponentFileList = uploadFiles;
    },
    pushUploadQueue(queueItem: platformUploadQueue) {
      this.platformUploadQueue.push(queueItem);
    },
    openUploadModal() {
      this.platformUploadModalShow = true;
      this.platformCurType = 'dataset';
    },
    closeUploadModal() {
      this.platformUploadModalShow = false;
    },

    async startUploadPrepare(dataset: CurrentDataset) {
      await this.refreshDatasetList();
      try {
        await this.prepareFileUploadId(dataset);
        await this.prepareUploadUrls(dataset);
        this.setCurUploadDataset(dataset);
        this.setCurProcessDatasetId(dataset.id);
        this.platformUploadLoading.beforeStartUploading = false;
      } catch (err) {
        console.log(err, 'err');
        this.platformUploadLoading.beforeStartUploading = false;
        ElMessage.error('任务初始化失败,请继续创建数据集');
        this.platformDeleteDatasetId.push(dataset.id);
        location.reload();
        return;
      }
    },
    async startUploadStart(dataset: CurrentDataset) {
      this.openUploadModal();
      await this.prepareUploadChunks(String(dataset.id));
      await this.startUpload(dataset);
    },
    async prepareUploadUrls(dataset: CurrentDataset) {
      const count = this.platformUploadFileList[dataset.id].length;
      let index = 0;

      return new Promise((resolve, reject) => {
        this.platformUploadFileList[dataset.id].map(async (item) => {
          try {
            const presignedUrlsResponse = await getPresignedUrls(
              getPresignedUrlsReq(
                dataset,
                this.platformUploadIdMapper[dataset.id][item.name]
              )
            );
            const urls = presignedUrlsResponse.data.urls;
            this.platformUploadUrlsMapper[dataset.id] =
              this.platformUploadUrlsMapper[dataset.id] || {};
            this.platformUploadUrlsMapper[dataset.id][item.name] = urls;
            index++;

            if (count == index) {
              resolve('success');
            }
          } catch (e) {
            console.log(e, 'e');
            return reject('init fail');
          }
        });
      });
    },
    async initPlatformUploadList() {
      const uploadListResponse = await getUploadList();
      this.platformUploadList = uploadListResponse.data;
    },
    async refreshDatasetList() {
      this.platformDatasetStatusChange = !this.platformDatasetStatusChange;
    },
    async prepareFileUploadId(dataset: CurrentDataset) {
      this.clearVueUploadComponentFileList(dataset);

      const count = this.platformUploadFileList[dataset.id].length;
      let index = 0;
      return new Promise((resolve, reject) => {
        this.platformUploadFileList[dataset.id].map(async (item) => {
          try {
            const uploadIdResponse = await getUploadId(
              getUploadReq(
                dataset,
                `${dataset.project_id}_${dataset.id}_${dataset.version_id}_${item.name}`,
                item.size!,
                item.name,
                this.platformChunkSize
              )
            );
            this.platformUploadIdMapper[dataset.id] =
              this.platformUploadIdMapper[dataset.id] || {};
            this.platformUploadIdMapper[dataset.id][item.name] =
              uploadIdResponse.data.upload_id;

            index++;
            if (index == count) {
              await this.initPlatformUploadList();
              resolve('success');
            }
          } catch (e) {
            return Promise.reject('init fail');
          }
        });
      });
    },

    setVueUploadComponentFileListEmpty() {
      this.vueUploadComponentFileList = [];
    },
    clearVueUploadComponentFileList(dataset: CurrentDataset) {
      this.platformUploadFileList[dataset.id] = [
        ...(this.vueUploadComponentFileList as PlatformUploadUserFile[]),
      ];
      this.platformUploadFileList[dataset.id].forEach((uploadListItem) => {
        uploadListItem.dataset_id = dataset.id;
        uploadListItem.version_id = dataset.version_id;
      });
      this.vueUploadComponentFileList = [];
    },

    async startUpload(
      dataset: CurrentDataset,
      uploaded?: Record<string, Record<string, string[]>>
    ) {
      // debugger;
      const chunkKeys = Object.keys(
        this.platformDataSetFileContainer[dataset.id].fileChunks
      );
      const noChunkKeys = Object.keys(
        this.platformDataSetFileContainer[dataset.id].fileNoChunks
      );

      if (!chunkKeys.length && !noChunkKeys.length) return;

      const formDataNoChunks: FormDataNoChunks[] = [];
      this.prepareNoChunksFormData(noChunkKeys, dataset, formDataNoChunks);
      await this.startUploadNoChunksFormData(
        formDataNoChunks,
        dataset,
        uploaded
      );
      const formDataChunks: FormDataChunks = {};
      await this.prepareChunksFormData(
        chunkKeys,
        dataset,
        formDataChunks,
        uploaded
      );
      const formDataKeys = Object.keys(formDataChunks);
      await this.starUploadChunksFormData(
        formDataKeys,
        dataset,
        formDataChunks,
        uploaded
      );

      const successQueueItem = () => {
        // return Promise.reject(".....")
        return createdSuccessfully(getSuccessReq(dataset));
      };

      const cleanOperationsOfDataset = () => {
        return new Promise((resolve, reject) => {
          this.forceClean(String(dataset.id));
          resolve('success');
        });
      };

      const fetchDatasetStatusMutation = () => {
        return new Promise((resolve, reject) => {
          this.refreshDatasetList();
          resolve('success');
        });
      };

      const fetchUploadListStatusMutation = () => {
        return new Promise((resolve, reject) => {
          this.initPlatformUploadList();
          resolve('success');
        });
      };

      this.pushUploadQueue({
        ...this.platformCurrentUploadDataset,
        requestAsync: successQueueItem,
        action: 'final_success',
      });

      this.pushUploadQueue({
        dataset_id: -1,
        version_id: -1,
        project_id: '-1',
        action: '',
        requestAsync: cleanOperationsOfDataset,
      });

      this.pushUploadQueue({
        dataset_id: -1,
        version_id: -1,
        project_id: '-1',
        action: '',
        requestAsync: fetchUploadListStatusMutation,
      });

      this.pushUploadQueue({
        dataset_id: -1,
        version_id: -1,
        project_id: '-1',
        action: '',
        requestAsync: fetchDatasetStatusMutation,
      });
      this.platformRequestSignal = !this.platformRequestSignal;
    },
    forceClean(dataset_id: string) {
      this.platformDataSetFileContainer[dataset_id] = {
        fileChunks: {},
        fileNoChunks: {},
      };
      this.setCurProcessDatasetIds(
        this.platformCurrentProcessId.filter((id) => id != Number(dataset_id))
      );
      this.platformJumpRequestId = this.platformJumpRequestId.filter(
        (id) => id != Number(dataset_id)
      );
      this.cleanQueueOfDataset(Number(dataset_id));
      this.platformUploadIdMapper[dataset_id] = {};
      this.platformUploadUrlsMapper[dataset_id] = {};
      // delete this.platformDatasetUploadAction[dataset_id];
    },
    async prepareUploadChunks(dataset_id: string) {
      const fileRow = this.platformUploadFileList[dataset_id];
      this.platformDataSetFileContainer[dataset_id] = this
        .platformDataSetFileContainer[dataset_id] || {
        fileChunks: {},
        fileNoChunks: {},
      };
      if (!fileRow.length) return;
      let filename;
      for (const rowFile of fileRow) {
        filename = rowFile.name;
        if (rowFile.raw && rowFile.raw.size <= this.platformChunkSize) {
          this.platformDataSetFileContainer[dataset_id].fileNoChunks[filename] =
            [
              {
                file: rowFile.raw,
                size: rowFile.raw.size,
                percentage: 0,
                filename: rowFile.name,
              },
            ];
        } else {
          const fileChunkList = createFileChunk(
            rowFile.raw!,
            this.platformChunkSize
          );
          this.platformDataSetFileContainer[dataset_id].fileChunks[filename] =
            fileChunkList.map(({ file }, index) => ({
              chunk: file,
              hash: rowFile.name + '-' + index,
              index: index,
              filename: rowFile.name,
              percentage: 0,
              size: file.size,
              rowName: rowFile.name,
              rowSize: rowFile.size!,
            }));
        }
      }
    },
    async starUploadChunksFormData(
      formDataKeys: string[],
      dataset: CurrentDataset,
      formDataChunks: FormDataChunks,
      uploaded?: Record<string, Record<string, string[]>>
    ) {
      const count = formDataKeys.length;
      let index = 0;
      return new Promise((resolve, reject) => {
        if (!formDataKeys.length) resolve('');
        formDataKeys.map(async (key) => {
          try {
            const urls = this.platformUploadUrlsMapper[dataset.id][key];
            let isAddImportingStatusChangeFunc = false;
            let isAddUploadingStatusChange = false;

            formDataChunks[key].map((formDataChunk, index) => {
              const FileChunkItem = formDataChunk.blob;
              const UploadFileQueueItem = () => {
                // 测试数据集断点续传
                // if (index > 12) return Promise.reject('');

                return authedApi.request({
                  url: urls[formDataChunk.index!],
                  method: 'PUT',
                  data: FileChunkItem,
                  headers: { 'Content-Type': 'application/octet-stream' },
                  onUploadProgress: OnFileProgress(
                    this.platformDataSetFileContainer[dataset.id]?.fileChunks[
                      key
                    ][formDataChunk.index as number]
                  ),
                });
              };

              const MergeFileQueueItem = () => {
                // return Promise.reject('');
                return mergeChunks(
                  getDatasetReq(
                    dataset,
                    this.platformUploadIdMapper[dataset.id][key]
                  )
                );
              };

              const UpdateSuccessItem = () => {
                // return Promise.reject('');
                return updateStatus(
                  getDatasetReq(
                    dataset,
                    this.platformUploadIdMapper[dataset.id][key]
                  )
                );
              };

              const importQueueItem = () => {
                // return Promise.reject("211")
                return importFile(getImportReq(dataset, formDataChunk.key));
              };

              const UpdateImporting = () => {
                return updateImporting({
                  project_id: dataset.project_id,
                  dataset_id: dataset.id,
                  version_id: dataset.version_id,
                });
              };

              // const updateUploading = () => {

              // }

              const fetchDatasetStatusMutation = () => {
                return new Promise((resolve, reject) => {
                  this.platformDatasetStatusChange =
                    !this.platformDatasetStatusChange;
                  resolve('success');
                });
              };

              if (formDataChunk.action == 'merge') {
                if (uploaded) {
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadDataset,
                    requestAsync: UpdateImporting,
                    action: '',
                  });
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadDataset,
                    requestAsync: () => this.refreshDatasetList(),
                    action: '',
                  });
                }
                this.pushUploadQueue({
                  ...this.platformCurrentUploadDataset,
                  requestAsync: MergeFileQueueItem,
                  action: 'merge',
                  id: Number(formDataChunk.id),
                });
              } else if (formDataChunk.action == 'import') {
                if (uploaded) {
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadDataset,
                    requestAsync: UpdateImporting,
                    action: '',
                  });
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadDataset,
                    requestAsync: () => this.refreshDatasetList(),
                    action: '',
                  });
                }
                this.pushUploadQueue({
                  ...this.platformCurrentUploadDataset,
                  requestAsync: importQueueItem,
                  action: 'import',
                  id: Number(formDataChunk.id),
                });
              } else if (formDataChunk.action == 'upload') {
                if (uploaded && !isAddUploadingStatusChange) {
                  isAddUploadingStatusChange = true;
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadDataset,
                    requestAsync: UpdateImporting,
                    action: '',
                  });
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadDataset,
                    requestAsync: () => this.refreshDatasetList(),
                    action: '',
                  });
                }
                this.pushUploadQueue({
                  ...this.platformCurrentUploadDataset,
                  requestAsync: UploadFileQueueItem,
                  action: 'upload',
                  id: Number(formDataChunk.id),
                });
                this.platformRequestChunkSignal =
                  !this.platformRequestChunkSignal;
              } else if (formDataChunk.action == 'upload_successfully') {
                this.pushUploadQueue({
                  ...this.platformCurrentUploadDataset,
                  requestAsync: UpdateSuccessItem,
                  action: 'upload_successfully',
                  id: Number(formDataChunk.id),
                });

                if (uploaded) {
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadDataset,
                    requestAsync: () => this.refreshDatasetList(),
                    action: '',
                  });
                }
                if (!isAddImportingStatusChangeFunc) {
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadDataset,
                    requestAsync: fetchDatasetStatusMutation,
                    action: '',
                  });
                  isAddImportingStatusChangeFunc = true;
                }
              }
            });

            // debugger;
            // console.log(this.pushUploadQueue, 'queue')
            // console.log(this.platformMaxUploadRequestNum, 'num')
            index++;
            this.platformRequestChunkSignal = !this.platformRequestChunkSignal;
            if (index === count) {
              resolve('success');
            }
          } catch (e) {
            location.reload();
            this.forceClean(String(dataset.id));
            await Promise.all([
              this.initPlatformUploadList(),
              this.refreshDatasetList(),
            ]);
          }
        });
      });
    },
    async prepareChunksFormData(
      chunkKeys: string[],
      dataset: CurrentDataset,
      formDataChunks: FormDataChunks,
      uploaded?: Record<string, Record<string, string[]>>
    ) {
      if (!chunkKeys.length) return;
      const count = chunkKeys.length;
      let i = 0;
      return new Promise((resolve, reject) => {
        /* 后上传大文件切片 */
        chunkKeys.map(async (key) => {
          try {
            const fileResponse = await getFileId({
              project_id: dataset.project_id,
              dataset_id: dataset.id,
              version_id: dataset.version_id,
              upload_id: this.platformUploadIdMapper[dataset.id][key],
            });
            const fileInfo = fileResponse.data;
            const id = fileInfo.id;
            const item_error_status = fileInfo.error_status;
            const item_progress = fileInfo.progress;
            const item_status = fileInfo.status;

            this.platformDataSetFileContainer[dataset.id].fileChunks[key].map(
              async (fileChunk) => {
                const { hash, chunk, index, filename } = fileChunk;
                if (
                  uploaded &&
                  uploaded[dataset.id][key]?.includes(String(index))
                )
                  return;
                const formData = new FormData();
                formData.append('file', chunk!);
                formData.append('hash', hash);
                formData.append('filename', filename);
                formDataChunks[key] = formDataChunks[key] || [];
                formDataChunks[key].push({
                  formData: formData,
                  blob: chunk!,
                  index: index,
                  key: key,
                  action: 'upload',
                  id: String(id),
                });
              }
            );
            if (uploaded) {
              // 续传 v3.0
              // debugger;
              if (item_error_status) {
                if (item_error_status == 'upload') {
                  formDataChunks[key].push({
                    key: key,
                    action: 'upload_successfully',
                    id: String(id),
                  });
                  formDataChunks[key].push({
                    key: key,
                    action: 'merge',
                    id: String(id),
                  });
                  formDataChunks[key].push({
                    key: key,
                    action: 'import',
                    id: String(id),
                  });
                } else if (item_error_status == 'upload_successfully') {
                  formDataChunks[key] = [];
                  formDataChunks[key].push({
                    key: key,
                    action: 'upload_successfully',
                    id: String(id),
                  });
                  formDataChunks[key].push({
                    key: key,
                    action: 'merge',
                    id: String(id),
                  });
                  formDataChunks[key].push({
                    key: key,
                    action: 'import',
                    id: String(id),
                  });
                } else if (item_error_status == 'merge') {
                  formDataChunks[key] = [];
                  formDataChunks[key].push({
                    key: key,
                    action: 'merge',
                    id: String(id),
                  });
                  formDataChunks[key].push({
                    key: key,
                    action: 'import',
                    id: String(id),
                  });
                } else if (item_error_status == 'import') {
                  formDataChunks[key] = [];
                  formDataChunks[key].push({
                    key: key,
                    action: 'import',
                    id: String(id),
                  });
                } else {
                  formDataChunks[key] = [];
                }
              } else {
                if (item_status == 'success' || item_progress >= 100) {
                  formDataChunks[key] = [];
                } else {
                  formDataChunks[key].push({
                    key: key,
                    action: 'upload_successfully',
                    id: String(id),
                  });
                  formDataChunks[key].push({
                    key: key,
                    action: 'merge',
                    id: String(id),
                  });
                  formDataChunks[key].push({
                    key: key,
                    action: 'import',
                    id: String(id),
                  });
                }
              }
              i++;
              if (count == i) {
                resolve('success');
              }
            } else {
              formDataChunks[key].push({
                key: key,
                action: 'upload_successfully',
                id: String(id),
              });
              formDataChunks[key].push({
                key: key,
                action: 'merge',
                id: String(id),
              });
              formDataChunks[key].push({
                key: key,
                action: 'import',
                id: String(id),
              });
              i++;
              if (count == i) {
                resolve('success');
              }
            }
          } catch (e) {
            this.platformDeleteDatasetId.push(dataset.id);
            location.reload();
            this.forceClean(String(dataset.id));
            await Promise.all([
              this.initPlatformUploadList(),
              this.refreshDatasetList(),
            ]);
          }
        });
      });
    },
    prepareNoChunksFormData(
      noChunkKeys: string[],
      dataset: CurrentDataset,
      fileNoChunk: FormDataNoChunks[]
    ) {
      if (!noChunkKeys.length) return;
      noChunkKeys.map(async (key) => {
        const blobFile =
          this.platformDataSetFileContainer[dataset.id].fileNoChunks[key][0]
            .file;
        fileNoChunk.push({ formData: blobFile, key });
      });
    },

    async startUploadNoChunksFormData(
      noChunks: FormDataNoChunks[],
      dataset: CurrentDataset,
      uploaded?: Record<string, Record<string, string[]>>
    ) {
      let index = 0;
      const count = noChunks.length;

      return new Promise((resolve, reject) => {
        if (!noChunks.length) resolve('success');
        noChunks.map(async ({ formData, key }) => {
          try {
            const noChunksBlob = formData;
            const fileResponse = await getFileId({
              project_id: dataset.project_id,
              dataset_id: dataset.id,
              version_id: dataset.version_id,
              upload_id: this.platformUploadIdMapper[dataset.id][key],
            });
            const fileInfo = fileResponse.data;
            const id = fileInfo.id;
            const item_error_status = fileInfo.error_status;
            const item_progress = fileInfo.progress;
            const item_status = fileInfo.status;
            const url = this.platformUploadUrlsMapper[dataset.id][key][0];

            const UploadFileQueueItem = () => {
              // 测试数据集断点续传
              // debug no delete version
              // location.reload();
              // return Promise.reject('111');
              return authedApi.request({
                url,
                method: 'PUT',
                data: noChunksBlob,
                headers: { 'Content-Type': 'application/octet-stream' },
                onUploadProgress: OnFileProgress(
                  this.platformDataSetFileContainer[dataset.id].fileNoChunks[
                    key
                  ][0]
                ),
              });
            };

            const importQueueItem = () => {
              // return Promise.reject("1111")
              return importFile(getImportReq(dataset, key));
            };

            const MergeFileQueueItem = () => {
              // return Promise.reject('1111');
              return mergeChunks(
                getDatasetReq(
                  dataset,
                  this.platformUploadIdMapper[dataset.id][key]
                )
              );
            };

            const UpdateSuccessItem = () => {
              // return Promise.reject("1111")
              return updateStatus(
                getDatasetReq(
                  dataset,
                  this.platformUploadIdMapper[dataset.id][key]
                )
              );
            };
            const addNoChunksQueue = () => {
              this.pushUploadQueue({
                action: 'upload',
                id: id,
                ...this.platformCurrentUploadDataset,
                requestAsync: UploadFileQueueItem,
              });
              this.pushUploadQueue({
                id: id,
                action: 'upload_successfully',
                ...this.platformCurrentUploadDataset,
                requestAsync: UpdateSuccessItem,
              });
              this.pushUploadQueue({
                id: id,
                action: 'merge',
                ...this.platformCurrentUploadDataset,
                requestAsync: MergeFileQueueItem,
              });
              this.pushUploadQueue({
                id: id,
                action: 'import',
                ...this.platformCurrentUploadDataset,
                requestAsync: importQueueItem,
              });
            };
            if (uploaded) {
              // 续传 v3.0
              // debugger;
              if (item_error_status) {
                if (item_error_status == 'upload') {
                  addNoChunksQueue();
                } else if (item_error_status == 'upload_successfully') {
                  this.pushUploadQueue({
                    id: id,
                    action: 'upload_successfully',
                    ...this.platformCurrentUploadDataset,
                    requestAsync: UpdateSuccessItem,
                  });
                  this.pushUploadQueue({
                    id: id,
                    action: 'merge',
                    ...this.platformCurrentUploadDataset,
                    requestAsync: MergeFileQueueItem,
                  });
                  this.pushUploadQueue({
                    id: id,
                    action: 'import',
                    ...this.platformCurrentUploadDataset,
                    requestAsync: importQueueItem,
                  });
                } else if (item_error_status == 'merge') {
                  this.pushUploadQueue({
                    id: id,
                    action: 'merge',
                    ...this.platformCurrentUploadDataset,
                    requestAsync: MergeFileQueueItem,
                  });
                  this.pushUploadQueue({
                    id: id,
                    action: 'import',
                    ...this.platformCurrentUploadDataset,
                    requestAsync: importQueueItem,
                  });
                } else if (item_error_status == 'import') {
                  this.pushUploadQueue({
                    id: id,
                    action: 'import',
                    ...this.platformCurrentUploadDataset,
                    requestAsync: importQueueItem,
                  });
                } else {
                }
              } else {
                if (item_progress >= 100 || item_status == 'success') {
                } else {
                  addNoChunksQueue();
                }
              }
            } else {
              addNoChunksQueue();
            }
            index++;
            this.platformRequestChunkSignal = !this.platformRequestChunkSignal;
            if (index == count) {
              this.platformRequestSignal = !this.platformRequestSignal;
              resolve('success');
            }
          } catch (e) {
            this.platformDeleteDatasetId.push(dataset.id);
            this.forceClean(String(dataset.id));
            location.reload();
            await Promise.all([
              this.initPlatformUploadList(),
              this.refreshDatasetList(),
            ]);
          }
        });
      });
    },
    async startScheduler() {
      if (
        this.platformUploadCount > this.platformMaxUploadRequestNum ||
        !this.platformUploadQueue.length
      )
        return;

      const uploadRequest = this.platformUploadQueue.shift();

      if (uploadRequest) {
        const action = uploadRequest.action;
        uploadRequest.requestAsync().then(
          () => this.platformUploadCount--,
          async () => {
            this.platformJumpRequestId.push(uploadRequest.dataset_id!);
            try {
              if (action) {
                if (uploadRequest.id) {
                  await updateItemStatus({
                    dataset_id: uploadRequest.dataset_id!,
                    project_id: uploadRequest.project_id!,
                    version_id: uploadRequest.version_id!,
                    status: action,
                    id: uploadRequest.id!,
                  });
                  await uploadErrorQueueItem({
                    dataset_id: uploadRequest.dataset_id!,
                    project_id: uploadRequest.project_id!,
                    version_id: uploadRequest.version_id!,
                    action,
                  });
                } else {
                  await uploadErrorQueueItem({
                    dataset_id: uploadRequest.dataset_id!,
                    project_id: uploadRequest.project_id!,
                    version_id: uploadRequest.version_id!,
                    action,
                  });
                }

                this.closeUploadModal();
                this.forceClean(String(uploadRequest.dataset_id));
                this.platformUploadCount--;
                ElMessage.error('上传发生错误，请继续上传');
              }
              await Promise.all([
                this.initPlatformUploadList(),
                this.refreshDatasetList(),
              ]);
            } catch (e: any) {
              this.platformFailureDatasetId.push(
                Number(uploadRequest?.dataset_id)
              );
              location.reload();
              this.forceClean(String(uploadRequest.dataset_id));
              await Promise.all([
                this.initPlatformUploadList(),
                this.refreshDatasetList(),
              ]);
              this.platformUploadCount--;
            }
          }
        );
        this.platformRequestSignal = !this.platformRequestSignal;
        this.platformUploadCount++;
      }
    },
    cleanQueueOfDataset(id: number) {
      this.platformUploadQueue = this.platformUploadQueue.filter(
        (q) => q.dataset_id != id
      );
    },
  },

  persist: {
    enabled: true,
    strategies: [
      {
        storage: localStorage,
        paths: ['platformFailureDatasetId', 'platformCurrentProcessId'],
        key: 'platformUploadErrorQueue',
      },
      {
        storage: localStorage,
        paths: ['platformDeleteDatasetId'],
        key: 'platformUploadDeleteQueue',
      },
    ],
  },
});

type FileRowChuck = { file: Blob }[];

interface FormDataChunk {
  formData?: FormData;
  blob?: Blob;
  index?: number;
  key: string;
  id: string;
  action:
    | 'merge'
    | 'upload'
    | 'import'
    | 'upload_successfully'
    | 'clean_chunks';
}

export type FormDataChunks = Record<string, FormDataChunk[]>;

export interface FormDataNoChunks {
  formData: File;
  key: string;
}

export interface FileChunk {
  chunk?: Blob;
  hash: string;
  index: number;
  size: number;
  filename: string;
  percentage: number;
  rowSize: number;
  rowName: string;
}

export interface FileNoChunk {
  file: File;
  percentage: number;
  size: number;
  filename: string;
}

export interface fileChunks {
  dataset_id: number;
  version_id: number;
  chunks: Record<string, FileChunk[]>;
}

export interface FileContainer {
  fileChunks: Record<string, FileChunk[]>;
  fileNoChunks: Record<string, FileNoChunk[]>;
}

export interface CurrentDataset {
  id: number;
  title: string;
  version_id: number;
  project_id: string;
  version_title: string;
}

export interface UploadList {
  id: number;
  identifier: string;
  total_size: number;
  progress: number;
  dataset_title: string;
  version_title: string;
  status: string;
  row_name: string;
  create_time: string;
  dataset_id: number;
  version_id: number;
  upload_id: string;
  error_status: string;
}

export interface PlatformUploadUserFile extends UploadUserFile {
  dataset_id: number;
  version_id: number;
}

export interface platformUploadQueue {
  dataset_id: number;
  action: string;
  version_id: number;
  project_id: string;
  requestAsync: () => Promise<any>;
  id?: number;
}
